#!/usr/bin/env python
#
# Copyright 2009 Benjamin Davis
#
# This file is part of resistencia.
#
# resistencia is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# resistencia is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with resistencia.  If not, see <http://www.gnu.org/licenses/>.

from commands import *
from dungeons import *
from items import *

class Player(object):
    """Player baseclass. Could be subclassed to allow players with different
    command-sets, such as moderators. Created when a client uses the 'register'
    command"""
    def __init__(self, client, name, password):
        # Set up the list of available commands
        # Commands can be assigned multiple aliases, the string passed to it
        # is the command that the player is required to type
        # This makes support for multiple languages easier
        self.commands = [Take("pick up"), Take("take"), List("list"),
        List("inventory"), Look("look"), LookAt("look at"), LookIn("look in"),
        Help("help"), Help("commands"), Drop("drop"), Say("say"), Drop("put"),
        Say("."), Give("give"), Emote("emote"), Emote(":"), Use("use")]
        self.client   = client
        self.items    = Items([])
        self.room     = None
        self.name     = name
        self.password = password
        
    def enter(self, room, direction):
        """Put the player cleanly into a new room"""
        try:
            try:
                # Remove player from old room
                self.room.players.remove(self)
                for someone in self.room.players:
                    if someone != self:
                        someone.client.send(self.name + " leaves to " + direction + ".")
            # If the player is in no room, i.e. when logging in
            except ValueError:
                pass
        except AttributeError:
            pass
        # Add player to new room
        self.room = room
        self.room.players.append(self)
        # Broadcast that the player has entered
        for someone in self.room.players:
            if someone != self:
                someone.client.send(self.name + " enters from " + direction + ".")
        # Automatically call 'look' for the player
        self.do("look")
    
    def do(self, data):
        """Acts on data inputted by the player"""
        commands = []
        # For each command
        for command in self.commands:
            # If the data starts with a command name
            if data.startswith(command):
                # Then add command to the list
                commands.append(command)
        # If at least one matching command was found
        if len(commands) > 0:
            commands.sort()
            commands.reverse()
            # Automatically take the longest matching command
            commands[0].run(self, data[len(commands[0]):].strip())
        # If there was no matching command
        else:
            # Try to find an item by that name
            item = (self.items + self.room.items).by_name(data)
            # If found
            if item:
                # Try to call the item, same as 'use <item>'
                call = item(self)
                # If item isn't callable
                if not call:
                    # Send an error message
                    self.client.send("Couldn't find command.")
            # If we can't find an item by that name, the command was erroneous
            else:
                # Send an error message
                self.client.send("Couldn't find command.")
        # Send an empty line
        self.client.send()
        
class Players(list):
    """Extends the list class to provide searching for a player by name.
    See the mud.items.Items class for more information"""
    def __add__(self, other):
        return Players(list.__add__(self, other))
    
    def by_name(self, name):
        for player in self:
            if name.strip() == player.name:
                return player
        return False
